package com.zqxq.lottery.service.order.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zqxq.common.utils.BigDecimalUtils;
import com.zqxq.common.utils.DispatcherUtils;
import com.zqxq.common.utils.StrUtils;
import com.zqxq.lottery.common.utils.FootBallBetUtils;
import com.zqxq.lottery.config.YmlConfig;
import com.zqxq.lottery.entity.bo.sys.SysActivityBO;
import com.zqxq.lottery.entity.enums.ActivityIdEnum;
import com.zqxq.lottery.entity.enums.LotteryIdEnum;
import com.zqxq.lottery.entity.po.export.ExpertInfoPO;
import com.zqxq.lottery.entity.po.order.*;
import com.zqxq.lottery.entity.po.sys.LotteryHnumPO;
import com.zqxq.lottery.entity.po.sys.SysConfigPO;
import com.zqxq.lottery.entity.po.user.UserCashPO;
import com.zqxq.lottery.entity.po.user.UserFundsPO;
import com.zqxq.lottery.entity.po.user.UserInfoPO;
import com.zqxq.lottery.entity.vo.esports.ESportsPlaywayVO;
import com.zqxq.lottery.entity.vo.jczq.JczqMatchLiveVO;
import com.zqxq.lottery.entity.vo.jczq.JczqMatchVO;
import com.zqxq.lottery.entity.vo.order.PushOrderDetailVO;
import com.zqxq.lottery.mapper.expert.ExpertInfoMapper;
import com.zqxq.lottery.mapper.order.*;
import com.zqxq.lottery.mapper.sys.LotteryHnumMapper;
import com.zqxq.lottery.mapper.sys.SysConfigMapper;
import com.zqxq.lottery.mapper.user.UserCashMapper;
import com.zqxq.lottery.mapper.user.UserFundsMapper;
import com.zqxq.lottery.mapper.user.UserInfoMapper;
import com.zqxq.lottery.service.esports.IESportsPlaywayService;
import com.zqxq.lottery.service.expert.IExpertInfoService;
import com.zqxq.lottery.service.jczq.IJczqMatchResultService;
import com.zqxq.lottery.service.jczq.IJczqMatchService;
import com.zqxq.lottery.service.order.IBonusCalcService;
import com.zqxq.lottery.service.order.IUserOrderService;
import com.zqxq.lottery.service.sys.ISysActivityService;
import com.zqxq.lottery.service.user.IUserMsgService;
import com.zqxq.lottery.service.user.IUserWindowMsgService;
import com.zqxq.lottery.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 说    明：  奖金计算
 * 创 建 人：	一刀·胡
 * 创建时间：	2018/7/1 22:09
 * 修 改 人：
 * 修改日期：
 **/
@Service
@Slf4j
public class BonusCalcServiceImpl extends ServiceImpl<UserOrderMapper,UserOrderPO> implements IBonusCalcService {
    private String msg_win = "恭喜，您的竞猜足球（电竞、欢乐猜球）订单中得趣豆%s个，盈利%s个。";
    public static final String robot_prefix = "ROBOT*";//这个*一定要加，否则无法模糊查询
    @Autowired
    private YmlConfig ymlConfig;
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private UserOrderBetMapper userOrderBetMapper;
    @Autowired
    private UserOrderBetBopMapper userOrderBetBopMapper;
    @Autowired
    private LotteryHnumMapper lotteryHnumMapper;
    @Autowired
    private UserFundsMapper userFundsMapper;
    @Autowired
    private UserCashMapper userCashMapper;
    @Autowired
    private CalculatorSSQ calculatorSSQ;
    @Autowired
    private CalculatorDLT calculatorDLT;
    @Autowired
    private CalculatorFC calculatorFC;
    @Autowired
    private CalculatorPL calculatorPL;
    @Autowired
    private CalculatorQXC calculatorQXC;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private IJczqMatchResultService jczqMatchResultService;
    @Autowired
    private IJczqMatchService jczqMatchService;
    @Autowired
    private UserOrderMapper userOrderMapper;
    @Autowired
    private ISysActivityService sysActivityService;
    @Autowired
    private FollowOrderMapper followOrderMapper;
    @Autowired
    private ExpertInfoMapper expertInfoMapper;
    @Autowired
    private IUserMsgService userMsgService;
    @Autowired
    private IUserWindowMsgService userWindowMsgService;
    @Autowired
    private IESportsPlaywayService eSportsPlaywayService;
    @Autowired
    private IUserOrderService userOrderService;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private IExpertInfoService expertInfoService;
    @Autowired
    private RobotOrderDataMapper robotOrderDataMapper;

    //足彩中奖后对订单数据进行操作
    public void winUserOrder(UserOrderPO order, BigDecimal rewards, BigDecimal afterTaxs) {
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        Long userId  = order.getUser_id();
        if(rewards.compareTo(BigDecimal.ZERO)==1){
            //订单中奖
            order.setPrize(rewards);
            order.setAfter_tax(afterTaxs);
            order.setStatus(5);
            userMsgService.saveUserMsg(userId,String.format(msg_win,afterTaxs,afterTaxs.subtract(order.getPay_amount()).setScale(2,BigDecimal.ROUND_HALF_UP)),3);
            if(order.getLottery_id()==21L){
                userWindowMsgService.saveUserMsg(userId,"恭喜您中奖了", String.valueOf(afterTaxs.intValue()),1);
            } else if (order.getLottery_id()==10L) {
                userWindowMsgService.saveUserMsg(userId,"恭喜您中奖了", String.valueOf(afterTaxs.intValue()),6);
            }

            //首次中奖奖励
            Wrapper firstRewardOrderWrapper = new EntityWrapper();
            firstRewardOrderWrapper.eq("user_id", userId);
            firstRewardOrderWrapper.in("status", "5,6");
            firstRewardOrderWrapper.eq("ticket_status", "1");
            Integer firstRewardOrderCount = userOrderMapper.selectCount(firstRewardOrderWrapper);
            if(firstRewardOrderCount==0){
                Wrapper firstRewardOrderCashWrapper = new EntityWrapper();
                firstRewardOrderCashWrapper.eq("user_id", userId);
                firstRewardOrderCashWrapper.eq("type", "7");
                firstRewardOrderCashWrapper.eq("info", "用户首次中奖奖励");
                Integer firstRewardOrderCashCount = userCashMapper.selectCount(firstRewardOrderCashWrapper);
                if(firstRewardOrderCashCount==0) {
                    SysActivityBO sysActivityBO = new SysActivityBO();
                    sysActivityBO.setActivityId(ActivityIdEnum.FIRST_WIN_ORDER_REWARD.getId());
                    sysActivityBO.setUserId(userId);
                    sysActivityService.saveUserActivity(sysActivityBO);
                }
            }
            //今日首次中奖奖励
            Wrapper todayFirstWinWrapper = new EntityWrapper();
            todayFirstWinWrapper.eq("user_id", userId);
            todayFirstWinWrapper.like("create_time",f.format(new Date()));
            todayFirstWinWrapper.eq("type", "7");
            todayFirstWinWrapper.eq("info", "用户今日首次中奖奖励");
            Integer todayFirstWinCount = userCashMapper.selectCount(todayFirstWinWrapper);
            if(todayFirstWinCount==0){
                SysActivityBO sysActivityBO = new SysActivityBO();
                sysActivityBO.setActivityId(ActivityIdEnum.FIRST_TODAY_FIRST_WIN_REWARD.getId());
                sysActivityBO.setUserId(userId);
                sysActivityService.saveUserActivity(sysActivityBO);
            }
            //今日中奖3次
            Wrapper userOrderWinWrapper = new EntityWrapper();
            userOrderWinWrapper.eq("user_id", userId);
            userOrderWinWrapper.like("create_time",f.format(new Date()));
            userOrderWinWrapper.in("status", "5,6");
            userOrderWinWrapper.eq("ticket_status",1);
            Integer userOrderWinCount = userOrderMapper.selectCount(userOrderWinWrapper);
            if(userOrderWinCount>=2){
                Wrapper todayWin3Wrapper = new EntityWrapper();
                todayWin3Wrapper.eq("user_id", userId);
                todayWin3Wrapper.like("create_time",f.format(new Date()));
                todayWin3Wrapper.eq("type", "7");
                todayWin3Wrapper.eq("info", "用户今日中奖3次奖励");
                Integer todayWin3Count = userCashMapper.selectCount(todayWin3Wrapper);
                if(todayWin3Count==0){
                    SysActivityBO sysActivityBO = new SysActivityBO();
                    sysActivityBO.setActivityId(ActivityIdEnum.FIRST_TODAY_WIN_3_REWARD.getId());
                    sysActivityBO.setUserId(userId);
                    sysActivityService.saveUserActivity(sysActivityBO);
                }
            }

        }else{
            //订单未中奖
            order.setStatus(3);
            orderLosePrize(order);
        }
        order.setWin_time(new Date());
        order.setUpdate_time(null);
        baseMapper.updateById(order);
        //如果该订单为推单，连黑4场佣金锁定为0%，直到红单
        if(order.getFollow_status()!=null && order.getFollow_status()==2){
            //查询近4场的单
            List<UserOrderPO> userOrderPOList = userOrderMapper.queryNearlyFourOrder(userId);
            if(userOrderPOList!=null && userOrderPOList.size()==4){
                Integer count = 0;
                for(UserOrderPO userOrderPO : userOrderPOList){
                    if(userOrderPO.getStatus()==3 || userOrderPO.getStatus()==10){
                        //未中奖，记录次数
                        count++;
                    }
                }
                if(count==4){
                    //佣金锁定为0
                    ExpertInfoPO expertInfoPO = new ExpertInfoPO();
                    expertInfoPO.setMax(BigDecimal.ZERO);
                    Wrapper wrapper = new EntityWrapper();
                    wrapper.eq("user_id",userId);
                    expertInfoMapper.update(expertInfoPO,wrapper);
                }else{
                    //佣金还原为原始值
                    ExpertInfoPO expertInfoPO = new ExpertInfoPO();
                    expertInfoPO.setUser_id(userId);
                    expertInfoPO = expertInfoMapper.selectOne(expertInfoPO);
                    Integer rank = expertInfoPO.getRank();//专家等级
                    switch (rank){
                        case 1:
                            expertInfoPO.setMax(new BigDecimal(10));
                            break;
                        case 2:
                            expertInfoPO.setMax(new BigDecimal(20));
                            break;
                        case 3:
                            expertInfoPO.setMax(new BigDecimal(30));
                            break;
                    }
                    Wrapper wrapper = new EntityWrapper();
                    wrapper.eq("user_id",userId);
                    expertInfoMapper.update(expertInfoPO,wrapper);
                }
            }
        }
        //持久化机器人推单数据
        persistenceRobotData();
    }

    /**
     * @Author 苦智
     * @Description 持久化机器人跟单数据
     * @Date 11:29 2018/12/5
     * @Param []
     * @return void
     **/
    public void persistenceRobotData() {
        try {
            Set<String> keys = stringRedisTemplate.keys(robot_prefix);
            for(String key : keys){
                String orderId = key.replace("ROBOT", "");
                if (StrUtils.isNotEmpty(orderId)) {
                    PushOrderDetailVO pushOrderDetailVO = followOrderMapper.getFinishOrderById(orderId);
                    String follows = stringRedisTemplate.opsForValue().get(key);
                    //已完成的订单进行数据持久化
                    if (pushOrderDetailVO != null && pushOrderDetailVO.getMinFollowAmt() != null && StrUtils.isNotEmpty(follows)) {
                        RobotOrderDataPO robotOrderDataPO = new RobotOrderDataPO();
                        robotOrderDataPO.setOrder_id(Long.valueOf(orderId));
                        robotOrderDataPO = robotOrderDataMapper.selectOne(robotOrderDataPO);
                        if (robotOrderDataPO == null) {
                            robotOrderDataPO = new RobotOrderDataPO();
                            Long pkId = ymlConfig.getPkId();
                            BigDecimal follow_amt = pushOrderDetailVO.getMinFollowAmt().multiply(new BigDecimal(follows));
                            robotOrderDataPO.setId(pkId);
                            robotOrderDataPO.setOrder_id(Long.valueOf(orderId));
                            robotOrderDataPO.setFollows(Integer.valueOf(follows));
                            robotOrderDataPO.setFollow_amt(follow_amt);
                            Integer c = robotOrderDataMapper.insert(robotOrderDataPO);
                            if (c > 0){
                                stringRedisTemplate.delete(key);
                            }
                        }
                    }
                }
            }
        }catch (Exception e){
            log.error("持久化机器人跟单数据异常",e);
        }
    }

    private void orderLosePrize(UserOrderPO order) {
        try {
            long userId = order.getUser_id();
            Wrapper<UserOrderPO> wrapper = new EntityWrapper<>();
            wrapper.eq("user_id",userId);
            wrapper.in("status","3,4,5,6,10");
            Integer count = userOrderMapper.selectCount(wrapper);
            if (count == 0){
                //用户首单未中奖
                SysActivityBO sysActivityBO = new SysActivityBO();
                sysActivityBO.setActivityId(ActivityIdEnum.ORDER_LOST_PRIZE.getId());
                sysActivityBO.setOrderId(order.getId());
                sysActivityBO.setUserId(userId);
                sysActivityBO.setConditionMoney(order.getPay_amount());
                sysActivityService.saveUserActivity(sysActivityBO);
            }
        }catch (Exception e){
            log.info("用户首单未中奖ERROR:",e);
        }
    }

    @Transactional
    public void updateCalcUserOrders21(List<UserOrderPO>  orderList){
        for(UserOrderPO order:orderList){
            try {
                if(order.getIs_bonus_optimize()!=null && order.getIs_bonus_optimize()==0){
                    updateCalcUserOrderBonus21(order);
                }else{
                    updateCalcUserOrder21(order);
                }
            } catch (Exception e) {
                log.error(e.toString());
            }
        }
    }

    @Transactional
    public void updateCalcUserOrders24(List<UserOrderPO>  orderList){
        for(UserOrderPO order:orderList){
            try {
                if(order.getIs_bonus_optimize()!=null && order.getIs_bonus_optimize()==0){
                    updateCalcUserOrderBonus21(order);
                }else{
                    updateCalcUserOrder24(order);
                }
            } catch (Exception e) {
                log.error(e.toString());
            }
        }
    }

    @Transactional
    public void updateCalcUserOrders210(List<UserOrderPO>  orderList){
        for(UserOrderPO order:orderList){
            try {
                updateCalcUserOrder210(order);
            } catch (Exception e) {
                log.error(e.toString());
            }
        }
    }

    @Transactional
    public void updateCalcUserOrders10(List<UserOrderPO>  orderList){
        for(UserOrderPO order:orderList){
            try {
                updateCalcUserOrder10(order);
            } catch (Exception e) {
                log.error(e.toString());
            }
        }
    }

    public void updateCalcUserOrder21(UserOrderPO order) throws Exception{
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.DAY_OF_MONTH, -1);
        Date afterTomorrow = c.getTime();
        String dateStr = f.format(afterTomorrow);
        Date date = f.parse(dateStr);
        Long yesterdayTime = date.getTime();
        List<UserOrderBetPO> betList = userOrderBetMapper.selectOrderBetList(order.getId(), order.getLottery_id());
        List<List<Double>> doubleLists = new ArrayList<>();
        Integer finishMatchCount = 0;
        for (int i = 0; i < betList.size(); i++) {
            List<Double> doubleList = new ArrayList<>();
            UserOrderBetPO bet = betList.get(i);
            StringBuffer winInfo = new StringBuffer();
            Integer status = 3;
            JczqMatchLiveVO jczqMatchLiveVO = jczqMatchResultService.get(DispatcherUtils.parseLong(bet.getPeriod()));
            String[] redNums = bet.getRed_num().split("\\,");
            String[] blueNums = bet.getBlue_num().split("\\,");
            Long matchTime = Long.valueOf(jczqMatchLiveVO.getMatchTime());
            if (jczqMatchLiveVO == null || jczqMatchLiveVO.getId() == null || "0".equals(jczqMatchLiveVO.getStatus())
                    || "1".equals(jczqMatchLiveVO.getStatus())
                    || ("3".equals(jczqMatchLiveVO.getStatus()) && "-,-,-,-,-".equals(jczqMatchLiveVO.getResult()))
                    || ("2".equals(jczqMatchLiveVO.getStatus()) && matchTime>=yesterdayTime)
                    || ("4".equals(jczqMatchLiveVO.getStatus()) && matchTime>=yesterdayTime)
                    ) {
                return;
            }
            //已取消场次
            else if("5".equals(jczqMatchLiveVO.getStatus()) || ("2".equals(jczqMatchLiveVO.getStatus()) && matchTime<yesterdayTime) || ("4".equals(jczqMatchLiveVO.getStatus()) && matchTime<yesterdayTime)){
                status = 4;
                bet.setWin_info(bet.getRed_num());
                winInfo.append(bet.getRed_num()+",");
                String s = "";
                for(int j = 0;j<redNums.length;j++){
                    s+=",1";
                    doubleList.add(1.0);
                }
                bet.setBlue_num(s.substring(1));
                finishMatchCount++;
            }else {
                finishMatchCount++;
                String[] matchResult = jczqMatchLiveVO.getResult().split("\\,");
                /***************************************/
                //如果此订单为机器人推单且无跟单人，自动修改赛果为中奖
                ExpertInfoPO expertInfoPO = expertInfoService.getExpertInfo(order.getUser_id());
                Wrapper wrapper = new EntityWrapper();
                wrapper.eq("follow_order_id",order.getId());
                wrapper.eq("follow_status","1");
                Integer count = userOrderService.selectCount(wrapper);
                if(expertInfoPO!=null && expertInfoPO.getType()==1 && order.getFollow_status()==2 && count==0){
                    JczqMatchVO jczqMatchVO = jczqMatchService.get(bet.getPeriod());
                    JSONObject betOddsObj = JSONObject.parseObject(jczqMatchVO.getOdds());
                    StringBuffer afterRedNum = new StringBuffer();
                    StringBuffer afterBlueNum = new StringBuffer();
                    //修改投注结果
                    for(int l = 0; l < redNums.length; l++){
                        Integer redNum = Integer.valueOf(redNums[l]);
                        if(redNum>=0 && redNum<=2){
                            afterRedNum.append(matchResult[0]+",");
                            afterBlueNum.append(betOddsObj.get(matchResult[0])+",");
                        }else if(redNum>=3 && redNum<=5){
                            afterRedNum.append(matchResult[1]+",");
                            afterBlueNum.append(betOddsObj.get(matchResult[1])+",");
                        }else if(redNum>=6 && redNum<=14){
                            afterRedNum.append(matchResult[2]+",");
                            afterBlueNum.append(betOddsObj.get(matchResult[2])+",");
                        }else if(redNum>=15 && redNum<=45){
                            afterRedNum.append(matchResult[3]+",");
                            afterBlueNum.append(betOddsObj.get(matchResult[3])+",");
                        }else if(redNum>=46 && redNum<=53){
                            afterRedNum.append(matchResult[4]+",");
                            afterBlueNum.append(betOddsObj.get(matchResult[4])+",");
                        }
                    }
                    bet.setRed_num(afterRedNum.deleteCharAt(afterRedNum.length()-1).toString());
                    bet.setBlue_num(afterBlueNum.deleteCharAt(afterBlueNum.length()-1).toString());
                    redNums = bet.getRed_num().split("\\,");
                    blueNums = bet.getBlue_num().split("\\,");
                }
                /***************************************/
                for (int j = 0; j < redNums.length; j++) {
                    for (int k = 0; k < matchResult.length; k++) {
                        if(k == 0 && matchResult[0].equals("-")){
                            if(redNums[j].equals("0") || redNums[j].equals("1") || redNums[j].equals("2")) {
                                //如果胜平负没有开则按照1倍赔率来计算奖金（相当于本场比赛退款）
                                status = 4;
                                winInfo.append(redNums[j] + ",");
                                doubleList.add(1.0);
                            }
                        }else if(k == 1 && matchResult[1].equals("-")){
                            if(redNums[j].equals("3") || redNums[j].equals("4") || redNums[j].equals("5")) {
                                //如果让球胜平负没有开则按照1倍赔率来计算奖金（相当于本场比赛退款）
                                status = 4;
                                winInfo.append(redNums[j] + ",");
                                doubleList.add(1.0);
                            }
                        }

                        if (redNums[j].equals(matchResult[k])) {
                            //此号码中奖
                            status = 4;
                            winInfo.append(redNums[j] + ",");
                            String odds = blueNums[j];
                            doubleList.add(Double.valueOf(odds));
                        }
                    }
                }
            }
            if (!"".equals(winInfo.toString())) {
                doubleLists.add(doubleList);
                bet.setWin_info(winInfo.deleteCharAt(winInfo.length() - 1).toString());
            }
            bet.setStatus(status);
        }
        if(finishMatchCount==betList.size()){
            //比赛全部完成（包括已取消比赛），订单修改状态
            for (int i = 0; i < betList.size(); i++) {
                UserOrderBetPO bet = betList.get(i);
                userOrderBetMapper.updateOrderBet(bet);
            }
        }
        Double[][] arr = new Double[doubleLists.size()][];
        for (int i = 0; i < doubleLists.size(); i++) {
            List<Double> dls = doubleLists.get(i);
            arr[i] = dls.toArray(new Double[0]);
        }
        BigDecimal[] val = FootBallBetUtils.calcWinVal(order.getBet_bunch().split(","), arr, order.getBet_times());
        BigDecimal rewards = val[0].multiply(new BigDecimal(100));
        BigDecimal afterTaxs = val[1].multiply(new BigDecimal(100));
        //足彩中奖后对订单数据进行操作
        winUserOrder(order, rewards, afterTaxs);
    }

    public void updateCalcUserOrderBonus21(UserOrderPO order) throws Exception{
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.DAY_OF_MONTH, -1);
        Date afterTomorrow = c.getTime();
        String dateStr = f.format(afterTomorrow);
        Date date = f.parse(dateStr);
        Long yesterdayTime = date.getTime();
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("order_id",order.getId());
        List<UserOrderBetBopPO> betList = userOrderBetBopMapper.selectList(wrapper);
        BigDecimal rewards = BigDecimal.ZERO;
        for (int i = 0; i < betList.size(); i++) {
            UserOrderBetBopPO bet = betList.get(i);
            JSONArray betJsonArray = JSONArray.parseArray(bet.getBet_info());
            Integer winCount = 0;
            for(int j=0;j<betJsonArray.size();j++){
                JSONObject betJson = betJsonArray.getJSONObject(j);
                String period = String.valueOf(betJson.get("period"));
                JczqMatchLiveVO jczqMatchLiveVO = jczqMatchResultService.get(DispatcherUtils.parseLong(period));
                String redNum = String.valueOf(betJson.get("redNum"));
                Long matchTime = Long.valueOf(jczqMatchLiveVO.getMatchTime());
                if (jczqMatchLiveVO == null || jczqMatchLiveVO.getId() == null || "0".equals(jczqMatchLiveVO.getStatus())
                        || "1".equals(jczqMatchLiveVO.getStatus())
                        || ("3".equals(jczqMatchLiveVO.getStatus()) && "-,-,-,-,-".equals(jczqMatchLiveVO.getResult()))
                        || ("2".equals(jczqMatchLiveVO.getStatus()) && matchTime>=yesterdayTime)
                        || ("4".equals(jczqMatchLiveVO.getStatus()) && matchTime>=yesterdayTime)
                        ) {
                    return;
                }else if("5".equals(jczqMatchLiveVO.getStatus()) || ("2".equals(jczqMatchLiveVO.getStatus()) && matchTime<yesterdayTime) || ("4".equals(jczqMatchLiveVO.getStatus()) && matchTime<yesterdayTime)){
                }else {
                    String[] matchResult = jczqMatchLiveVO.getResult().split("\\,");
                    for (int k = 0; k < matchResult.length; k++) {
                        if (redNum.equals(matchResult[k])) {
                            //此号码中奖
                            winCount++;
                        }
                    }
                }
            }
            if(winCount==betJsonArray.size()){
                //此注中奖
                bet.setStatus(4);
                bet.setPrize(bet.getExpect_bonus());
                bet.setAfter_tax(bet.getExpect_bonus());
                rewards = rewards.add(bet.getExpect_bonus());
            }else{
                bet.setStatus(3);
            }
            userOrderBetBopMapper.updateOrderBet(bet);
        }
        winUserOrder(order, rewards, rewards);
    }

    public void updateCalcUserOrder24(UserOrderPO order) throws Exception{
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.DAY_OF_MONTH, -1);
        Date afterTomorrow = c.getTime();
        String dateStr = f.format(afterTomorrow);
        Date date = f.parse(dateStr);
        Long yesterdayTime = date.getTime();
        List<UserOrderBetPO> betList = userOrderBetMapper.selectOrderBetList(order.getId(), order.getLottery_id());
        List<List<Double>> doubleLists = new ArrayList<>();
        Integer finishMatchCount = 0;
        for (int i = 0; i < betList.size(); i++) {
            List<Double> doubleList = new ArrayList<>();
            UserOrderBetPO bet = betList.get(i);
            StringBuffer winInfo = new StringBuffer();
            Integer status = 3;
            JczqMatchLiveVO jczqMatchLiveVO = jczqMatchResultService.get(DispatcherUtils.parseLong(bet.getPeriod()));
            String[] redNums = bet.getRed_num().split("\\,");
            String[] blueNums = bet.getBlue_num().split("\\,");
            Long matchTime = Long.valueOf(jczqMatchLiveVO.getMatchTime());
            if (jczqMatchLiveVO == null || jczqMatchLiveVO.getId() == null || "0".equals(jczqMatchLiveVO.getStatus())
                    || "1".equals(jczqMatchLiveVO.getStatus())
                    || ("3".equals(jczqMatchLiveVO.getStatus()) && "-,-,-,-,-".equals(jczqMatchLiveVO.getResult()))
                    || ("2".equals(jczqMatchLiveVO.getStatus()) && matchTime>=yesterdayTime)
                    || ("4".equals(jczqMatchLiveVO.getStatus()) && matchTime>=yesterdayTime)
                    ) {
                return;
            }
            //已取消场次
            else if("5".equals(jczqMatchLiveVO.getStatus()) || ("2".equals(jczqMatchLiveVO.getStatus()) && matchTime<yesterdayTime) || ("4".equals(jczqMatchLiveVO.getStatus()) && matchTime<yesterdayTime)){
                status = 4;
                bet.setWin_info(bet.getRed_num());
                winInfo.append(bet.getRed_num()+",");
                String s = "";
                for(int j = 0;j<redNums.length;j++){
                    s+=",1";
                    doubleList.add(1.0);
                }
                bet.setBlue_num(s.substring(1));
                finishMatchCount++;
            }else {
                finishMatchCount++;
                String[] matchResult = jczqMatchLiveVO.getResult().split("\\,");
                for (int j = 0; j < redNums.length; j++) {
                    for (int k = 0; k < matchResult.length; k++) {
                        if (redNums[j].equals(matchResult[k])) {
                            //此号码中奖
                            status = 4;
                            winInfo.append(redNums[j] + ",");
                            String odds = blueNums[j];
                            doubleList.add(Double.valueOf(odds));
                        }
                    }
                }
            }
            if (!"".equals(winInfo.toString())) {
                doubleLists.add(doubleList);
                bet.setWin_info(winInfo.deleteCharAt(winInfo.length() - 1).toString());
            }
            bet.setStatus(status);
        }
        if(finishMatchCount==betList.size()){
            //比赛全部完成（包括已取消比赛），订单修改状态
            for (int i = 0; i < betList.size(); i++) {
                UserOrderBetPO bet = betList.get(i);
                userOrderBetMapper.updateOrderBet(bet);
            }
        }
        Double[][] arr = new Double[doubleLists.size()][];
        for (int i = 0; i < doubleLists.size(); i++) {
            List<Double> dls = doubleLists.get(i);
            arr[i] = dls.toArray(new Double[0]);
        }
        BigDecimal[] val = FootBallBetUtils.calcWinVal(order.getBet_bunch().split(","), arr, order.getBet_times());
        BigDecimal rewards = val[0].multiply(new BigDecimal(100));
        BigDecimal afterTaxs = val[1].multiply(new BigDecimal(100));
        //足彩中奖后对订单数据进行操作
        winUserOrder(order, rewards, afterTaxs);
    }

    public void updateCalcUserOrder210(UserOrderPO order) throws Exception{
        List<UserOrderBetPO> betList = userOrderBetMapper.selectOrderBetList(order.getId(), order.getLottery_id());
        UserOrderBetPO bet = betList.get(0);
        String[] redNums = bet.getRed_num().split("\\,");
        String[] blueNums = bet.getBlue_num().split("\\,");
        JczqMatchLiveVO jczqMatchLiveVO = jczqMatchResultService.get(DispatcherUtils.parseLong(bet.getPeriod()));
        if(jczqMatchLiveVO!=null && !StringUtils.isEmpty(jczqMatchLiveVO.getResult())){
            String matchResult = jczqMatchLiveVO.getResult().split("\\,")[0];
            if(!StringUtils.isEmpty(matchResult)){
                boolean winFalg = false;
                String odds = "";
                for(int i = 0; i < redNums.length; i++){
                    String redNum = redNums[i];
                    if(redNum.equals(matchResult)){
                        winFalg =true;
                        odds = blueNums[i];
                    }
                }
                BigDecimal rewards = BigDecimal.ZERO;
                BigDecimal afterTaxs = BigDecimal.ZERO;
                if(winFalg){
                    rewards = new BigDecimal(order.getBet_times()).multiply(new BigDecimal(2)).multiply(new BigDecimal(odds));
                    afterTaxs = rewards;
                    if(rewards.compareTo(new BigDecimal(10000))==1){
                        afterTaxs = afterTaxs.multiply(new BigDecimal("0.8"));
                    }
                }
                winUserOrder(order, rewards, afterTaxs);
            }
        }

    }

    public void updateCalcUserOrder10(UserOrderPO order) throws Exception{
        List<UserOrderBetPO> betList = userOrderBetMapper.selectOrderBetList(order.getId(), order.getLottery_id());
        UserOrderBetPO bet = betList.get(0);
        String redNum = bet.getRed_num();
        String odds = bet.getBlue_num();
        String period = bet.getPeriod();
        String playType = String.valueOf(bet.getPlay_type());
        ESportsPlaywayVO eSportsPlaywayVO = eSportsPlaywayService.getESportsPlayway(period,playType);
        //如果比赛取消，则订单取消
        if(eSportsPlaywayVO!=null && !StringUtils.isEmpty(eSportsPlaywayVO.getStatus()) && "3".equals(eSportsPlaywayVO.getStatus())){
            userOrderService.updateOrderCancel(order);
        }
        if(eSportsPlaywayVO!=null && !StringUtils.isEmpty(eSportsPlaywayVO.getStatus()) && "2".equals(eSportsPlaywayVO.getStatus()) && !StringUtils.isEmpty(eSportsPlaywayVO.getResult())){
            String matchResult = eSportsPlaywayVO.getResult();
            Map<String,Map<String,String>> oddsMap = JSONObject.parseObject(eSportsPlaywayVO.getPlayOdds(), Map.class);
//            odds = oddsMap.get(matchResult).get("partOdds");
            if(!StringUtils.isEmpty(matchResult)){
                boolean winFalg = false;
                if(redNum.equals(matchResult)){
                    winFalg =true;
                }
                BigDecimal rewards = BigDecimal.ZERO;
                BigDecimal afterTaxs = BigDecimal.ZERO;
                if(winFalg) {
                    rewards = order.getPay_amount().multiply(new BigDecimal(odds));
                    afterTaxs = rewards;
                }
                winUserOrder(order, rewards, afterTaxs);
            }
        }

    }


    /**
     * 说    明：   批量计算数字竞猜
     * 创 建 人：	一刀·胡
     * 创建时间：	2018/7/2 9:42
     * 修 改 人：
     * 修改日期：
     **/
    @Transactional
    public void updateCalcUserOrders(List<UserOrderPO> orderList,LotteryHnumPO lotteryNum){
        for(UserOrderPO order:orderList){
            updateCalcUserOrder(order,lotteryNum);
        }
    }

    //根据单个订单 进行中奖计算
    public void updateCalcUserOrder(UserOrderPO order, LotteryHnumPO lotteryNum) {
        order.setLottery_num(lotteryNum.getRed_num() + "|" + lotteryNum.getBlue_num());
        order.setCreate_time(null);
        order.setUpdate_time(null);
        List<UserOrderBetPO> betList = userOrderBetMapper.selectOrderBetList(order.getId(),lotteryNum.getLottery_id());
        Set<Integer> setStatus = new HashSet<>();
        //总金额
        BigDecimal prize = new BigDecimal(0);
        //税后金额
        BigDecimal tax = new BigDecimal(0);

        Calculator calculator = null;
        LotteryIdEnum e = LotteryIdEnum.getEnumById(order.getLottery_id());
        switch (e){
            case SSQ:calculator = calculatorSSQ;break;
            case DLT:calculator = calculatorDLT;break;
            case FC:calculator = calculatorFC;break;
            case PL:calculator = calculatorPL;break;
            case QXC:calculator = calculatorQXC;
        }
        for (UserOrderBetPO bet : betList) {
            setStatus.add(caclOrderBet(bet, lotteryNum, calculator));
        }
        //如果订单未领奖
        if (6 != order.getStatus()) {
            //已中奖【人工审核】
            if (setStatus.contains(4)) {
                order.setStatus(5);
                order.setPrize(prize);
                order.setAfter_tax(tax);
            }
            //待领奖
            else if (setStatus.contains(5)) {
                order.setStatus(5);
                for (UserOrderBetPO bet : betList) {
                    prize = prize.add(bet.getPrize());
                    tax = tax.add(bet.getAfter_tax());
                }
                order.setPrize(prize);
                order.setAfter_tax(tax);
                if (BigDecimalUtils.bigDecimalToLong(tax) > 10000L) {
                    order.setStatus(5);
                }
            }
            //未中奖
            else {
                order.setStatus(3);
                orderLosePrize(order);
            }
        }
        order.setWin_time(new Date());
        baseMapper.updateById(order);
    }


    //计算单注奖金中奖情况  返回每注状态
    private int caclOrderBet(UserOrderBetPO bet, LotteryHnumPO lotteryNumPO, Calculator calculator) {
        Long lotteryId = DispatcherUtils.parseLong(bet.getLottery_id());
        String bettingNum = bet.getRed_num();
        String lotteryNum = lotteryNumPO.getRed_num();
        //如果为双色球与大乐透就组装投注参数
        if(lotteryId == LotteryIdEnum.SSQ.getId()||lotteryId == LotteryIdEnum.DLT.getId()) {
            bettingNum = bet.getRed_num() + "|" + bet.getBlue_num();
            lotteryNum = lotteryNumPO.getRed_num() + "|" + lotteryNumPO.getBlue_num();
        }
        if (StrUtils.isEmpty(bettingNum) || StrUtils.isEmpty(lotteryNum)){
            bet.setStatus(4);
            return bet.getStatus();
        }
        Integer playType = bet.getPlay_type();
        if (playType == null){
            playType = 1;
        }
        String redNum = lotteryNumPO.getRed_num();
        String blueNum = lotteryNumPO.getBlue_num();
        int[] win = calculator.win(lotteryNum, bettingNum, playType+"");
        String winInfo = calculator.winInfo(win, bet.getBet_times());
        bet.setWin_info(winInfo);
        //双色球、大乐透、七星彩的一二等奖直接人工审核
        if ((bet.getLottery_id() == 11L || bet.getLottery_id() == 14L || bet.getLottery_id() ==15L ) && null != win && (win[0] > 0 || win[1] > 0)) {
            win = calculator.win(lotteryNum, bettingNum, bet.getPlay_type().toString());
            winInfo = calculator.winInfo(win, bet.getBet_times());
            bet.setWin_info(winInfo);
            bet.setStatus(4);
        }
        Long amount;
        //状态 0：待付款；1：待出票；2：待开奖；3：未中奖；4：已中奖【人工审核】；5：待领奖；6：已领奖；7：取消，8：支付中
        try {
            amount = DispatcherUtils.parseLong(winInfo);
            bet.setAfter_tax(new BigDecimal(amount));
            if (amount > 0) {
                bet.setPrize(new BigDecimal(amount));
                if (6 != bet.getStatus() || 4 != bet.getStatus()) {
                    bet.setStatus(5);
                }
            } else {
                bet.setStatus(3);
            }
        } catch (Exception e) {
            bet.setStatus(4);
            log.error("计算错误：" + e);
        }
//        userOrderBetMapper.updateById(bet);
        userOrderBetMapper.updateOrderBet(bet);
        return bet.getStatus();
    }


    /**
     * 说    明：   兑奖
     * 创 建 人：	一刀·胡
     * 创建时间：	2018/3/28 14:27
     * 修 改 人：
     * 修改日期：
     **/
    @Transactional
    public synchronized boolean updateOrderForPrize(UserOrderPO order) {
        String key = "ZQXQ_PRIZE_"+order.getId();
        String val = stringRedisTemplate.opsForValue().get(key);
        if(StrUtils.isNotEmpty(val))
            return false;
        try {
            //只处理待领奖状态
            if ( 5 == order.getStatus() && checkRedeemPrize(order)) {
                stringRedisTemplate.opsForValue().set(key,key);
                UserInfoPO user = userInfoMapper.selectById(order.getUser_id());
                UserFundsPO fund = userFundsMapper.selectForUpdate(user.getId());
                //插入 userCash 记录
                fund.setBalance(fund.getBalance().add(order.getAfter_tax()));
                if (null != fund) {
                    UserCashPO cash = new UserCashPO();
                    cash.setId(ymlConfig.getPkId());
                    cash.setUser_id(order.getUser_id());
                    cash.setReal_name(user.getReal_name());
                    cash.setMobile(user.getMobile());
                    cash.setPay_way(3);
                    cash.setPay_account(order.getId() + "");
                    cash.setType(3);
                    cash.setAuditor("SYS");
                    cash.setPay_amount(order.getAfter_tax());
                    cash.setRemainder(fund.getBalance());
                    cash.setStatus(4);
                    userCashMapper.insert(cash);
                    userFundsMapper.updateUserBalance(fund.getUser_id(), fund.getBalance());
                    order.setStatus(6);
                    order.setUpdate_time(null);
                    userOrderMapper.updateById(order);
                    log.info("该订单{} 领奖成功！", order.getId());
                    //如果该订单为跟单，开始分配佣金
                    if(order.getFollow_status()!=null && order.getFollow_status()==1){
                        sendCommission(order,user,fund);
                    }
                    return true;
                }
                log.info("用户{}资金不存在！");
            } else
                log.info("该订单{} 不能进行领奖，领奖失败！", order.getId());
        }catch (Exception e){
            log.error(e.toString());
        }finally {
            stringRedisTemplate.delete(key);
        }
        return false;
    }
    private void sendCommission(UserOrderPO order,UserInfoPO user,UserFundsPO fund){
        //1.扣除跟单人佣金
        Long followOrderId = order.getFollow_order_id();
        FollowOrderPO followOrderPO = new FollowOrderPO();
        followOrderPO.setOrder_id(followOrderId);
        followOrderPO = followOrderMapper.selectOne(followOrderPO);
        BigDecimal commissionRate = followOrderPO.getCommission_rate().divide(new BigDecimal(100)); //佣金比例
        BigDecimal afterTax = order.getAfter_tax();
        BigDecimal payAmount = order.getPay_amount();
        BigDecimal profit = afterTax.subtract(payAmount);
        BigDecimal profitRatio = profit.divide(payAmount ,2, BigDecimal.ROUND_HALF_UP);
        SysConfigPO sysConfigPO = sysConfigMapper.getByKey("INCOME_DISTRIBUTION_INITIAL");
        BigDecimal num = new BigDecimal(sysConfigPO.getCval());
        if(profitRatio.compareTo(num)!=-1 && commissionRate.compareTo(BigDecimal.ZERO)>0){
            //盈利率大于百分之十才发放佣金
            BigDecimal commission = profit.multiply(commissionRate);
            fund.setBalance(fund.getBalance().subtract(commission));
            UserCashPO userCashPO = new UserCashPO();
            userCashPO.setId(ymlConfig.getPkId());
            userCashPO.setUser_id(order.getUser_id());
            userCashPO.setReal_name(user.getReal_name());
            userCashPO.setMobile(user.getMobile());
            userCashPO.setPay_way(3);
            userCashPO.setPay_account(order.getId() + "");
            userCashPO.setType(6);
            userCashPO.setAuditor("SYS");
            userCashPO.setPay_amount(BigDecimal.ZERO.subtract(commission));
            userCashPO.setRemainder(fund.getBalance());
            userCashPO.setStatus(4);
            userCashMapper.insert(userCashPO);
            userFundsMapper.updateUserBalance(fund.getUser_id(), fund.getBalance());
            //2.奖励推单人佣金
            //判断当前奖励流水是否存在，如果存在不新增，累加金额上去
            UserOrderPO userOrderPO = userOrderMapper.selectById(followOrderId);
            Long userId = userOrderPO.getUser_id();
            UserInfoPO pushUser = userInfoMapper.selectById(userId);
            UserFundsPO pushFund = userFundsMapper.selectForUpdate(userId);
            pushFund.setBalance(pushFund.getBalance().add(commission));
            UserCashPO userCashPOFlag = new UserCashPO();
            userCashPOFlag.setUser_id(userId);
            userCashPOFlag.setReal_name(pushUser.getReal_name());
            userCashPOFlag.setMobile(pushUser.getMobile());
            userCashPOFlag.setPay_way(3);
            userCashPOFlag.setPay_account(userOrderPO.getId() + "");
            userCashPOFlag.setType(6);
            userCashPOFlag.setAuditor("SYS");
            userCashPOFlag.setStatus(4);
            UserCashPO userCashPOFlagResult = userCashMapper.selectOne(userCashPOFlag);
            if(userCashPOFlagResult!=null){
                BigDecimal flagPayAmount = userCashPOFlagResult.getPay_amount();
                userCashPOFlagResult.setPay_amount(flagPayAmount.add(commission));
                userCashPOFlagResult.setRemainder(pushFund.getBalance());
                Wrapper wrapper = new EntityWrapper();
                wrapper.eq("user_id",userId);
                wrapper.eq("mobile",pushUser.getMobile());
                wrapper.eq("pay_way",3);
                wrapper.eq("pay_account",userOrderPO.getId() + "");
                wrapper.eq("type",6);
                wrapper.eq("auditor","SYS");
                wrapper.eq("status",4);
                userCashMapper.update(userCashPOFlagResult,wrapper);
            }else{
                UserCashPO pushUserCashPO = new UserCashPO();
                pushUserCashPO.setId(ymlConfig.getPkId());
                pushUserCashPO.setUser_id(userId);
                pushUserCashPO.setReal_name(pushUser.getReal_name());
                pushUserCashPO.setMobile(pushUser.getMobile());
                pushUserCashPO.setPay_way(3);
                pushUserCashPO.setPay_account(userOrderPO.getId() + "");
                pushUserCashPO.setType(6);
                pushUserCashPO.setAuditor("SYS");
                pushUserCashPO.setPay_amount(commission);
                pushUserCashPO.setRemainder(pushFund.getBalance());
                pushUserCashPO.setStatus(4);
                userCashMapper.insert(pushUserCashPO);
            }
            userFundsMapper.updateUserBalance(pushFund.getUser_id(), pushFund.getBalance());
        }
    }
    private boolean checkRedeemPrize(UserOrderPO order){
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("user_id",order.getUser_id());
        wrapper.eq("pay_way",3);
        wrapper.eq("type",3);
        wrapper.eq("pay_account",order.getId());
        return userCashMapper.selectCount(wrapper)==0;
    }

    public List<UserOrderPO> queryDigitOrderForCal(Long lotteryId, String period){
        return userOrderMapper.queryDigitOrderForCal(lotteryId,period);
    }

    public List<UserOrderPO> query21OrderForCal(Long start,Long end){
        return userOrderMapper.query21OrderForCal(start,end);
    }

    public List<UserOrderPO> query24OrderForCal(Long start,Long end){
        return userOrderMapper.query24OrderForCal(start,end);
    }

    public List<UserOrderPO> query210OrderForCal(Long start,Long end){
        return userOrderMapper.query210OrderForCal(start,end);
    }

    public List<UserOrderPO> query10OrderForCal(Long start,Long end){
        return userOrderMapper.query10OrderForCal(start,end);
    }

    public Long getMaxOrderId21(){
        return userOrderMapper.getMaxOrderId21();
    }

    public Long getMaxOrderId24(){
        return userOrderMapper.getMaxOrderId24();
    }

    public Long getMaxOrderId210(){
        return userOrderMapper.getMaxOrderId210();
    }
    public Long getMaxOrderId10(){
        return userOrderMapper.getMaxOrderId10();
    }

    public List<UserOrderPO> queryOrderForPrize(Long lotteryId){
        return userOrderMapper.queryOrderForPrize(lotteryId);
    }
    public List<UserOrderPO> queryNotOpenPrizeOrder(){
        return userOrderMapper.queryNotOpenPrizeOrder();
    }


}
